package org.jeecg.modules.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dingtalk.api.request.OapiProcessinstanceGetRequest;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.taobao.api.ApiException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.checkerframework.checker.index.qual.LengthOf;
import org.jeecg.common.api.ding.DingApi;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.RoleInfo;
import org.jeecg.common.util.DySmsEnum;
import org.jeecg.common.util.DySmsHelper;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.config.CallBackEvent;
import org.jeecg.modules.config.Constant;
import org.jeecg.modules.config.URLConstant;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiCallBackDeleteCallBackRequest;
import com.dingtalk.api.request.OapiCallBackRegisterCallBackRequest;
import com.dingtalk.api.response.OapiCallBackRegisterCallBackResponse;
import com.dingtalk.oapi.lib.aes.DingTalkEncryptor;
import com.dingtalk.oapi.lib.aes.Utils;
import org.jeecg.modules.dinguser.service.IDiyDingUserService;
import org.jeecg.modules.entity.*;
import org.jeecg.modules.service.*;
import org.jeecg.modules.service.impl.ProjectOwnProfessorServiceImpl;
import org.jeecg.modules.temporary.entity.DiyTemporaryApplicantInfo;
import org.jeecg.modules.temporary.mapper.DiyTemporaryApplicantInfoMapper;
import org.jeecg.modules.temporary.service.impl.DiyTemporaryApplicantInfoServiceImpl;
import org.jeecg.modules.util.*;
import org.jeecg.modules.vo.ProfessorChoose;
import org.jeecg.modules.vo.ProjectUrgentStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * E应用回调信息处理
 */
@Slf4j
@RestController
public class CallbackController {

    private static final Logger bizLogger = LoggerFactory.getLogger("BIZ_CALLBACKCONTROLLER");
    private static final Logger mainLogger = LoggerFactory.getLogger(CallbackController.class);

    /**
     * 创建套件后，验证回调URL创建有效事件（第一次保存回调URL之前）
     */
    private static final String CHECK_URL = "check_url";

    /**
     * 审批任务回调
     */
    private static final String BPMS_TASK_CHANGE = "bpms_task_change";

    /**
     * 审批实例回调
     */
    private static final String BPMS_INSTANCE_CHANGE = "bpms_instance_change";

    /**
     * 相应钉钉回调时的值
     */
    private static final String CALLBACK_RESPONSE_SUCCESS = "success";


    private static RestTemplate restTemplate;
    @Autowired
    public  void setRestTemplate(RestTemplate restTemplate) {
        CallbackController.restTemplate = restTemplate;
    }
    @Autowired
    private CallbackService callbackService;
    @Autowired
    ProjectOwnProfessorServiceImpl projectOwnProfessorService;
    @Autowired
    private IDiyProfessorInfoService iDiyProfessorInfoService;
    @Autowired
    private  RedisTemplate redisTemplate;
    @Autowired
    private IDiyDingUserService dingUserService;
    @Autowired
    private IProjectProfessorInfoService projectProfessorInfoService;
    @Autowired
    private IDiyProjectProfessorService diyProjectProfessorService;
    @Autowired
    ISysBaseAPI iSysBaseAPI;
    @Autowired
    private IDiyProjectOwnProfessorTypeService diyProjectOwnProfessorTypeService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DiyTemporaryApplicantInfoServiceImpl diyTemporaryApplicantInfoService;
    @Autowired
    private IDiyDingUserService diyDingUserService;
    @Autowired
    private DingApi dingApi;
    @Autowired
    private  DiyProfessorScoreService diyProfessorScoreService;
    @Autowired
    private DiyProjectUrgentStatusService diyProjectUrgentStatusService;
    /**
     * 回调函数
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @param json
     * @return
     */
    @RequestMapping(value = "/callback", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> callback(@RequestParam(value = "signature", required = false) String signature,
                                        @RequestParam(value = "timestamp", required = false) String timestamp,
                                        @RequestParam(value = "nonce", required = false) String nonce,
                                        @RequestBody(required = false) JSONObject json,
                                        HttpServletRequest request) {
        String params = " signature:" + signature + " timestamp:" + timestamp + " nonce:" + nonce + " json:" + json;
        try {
            DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY,
                    Constant.CORP_ID);
            //从post请求的body中获取回调信息的加密数据进行解密处理
            String encryptMsg = json.getString("encrypt");
            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
            JSONObject obj = JSON.parseObject(plainText);
            log.info("获取到的审批对象"+obj);
            //当前的审批id
            String processInstanceId = obj.getString("processInstanceId");
            log.info("获取到当前的审批id--->"+processInstanceId);
            //开始：start；完成：finish；
            String type = obj.getString("type");
            //审批结果。同意：agree;拒绝：refuse;转送：redirect(当前值只有bpms_task_change能够接收到)
            String result = obj.getString("result");
            log.info("获取到的审批结果--->"+result);
            // 获取审批模板id
            String processCode = obj.getString("processCode");
            log.info("获取到的审批模板id--->"+processCode);
            //根据回调数据类型做不同的业务处理
            String eventType = obj.getString("EventType");
            log.info("类型------->"+eventType);
            if (BPMS_TASK_CHANGE.equals(eventType)) {
                // 收到审批任务进度
                bizLogger.info("收到审批任务进度更新: " + plainText);
                String body = callbackService.getInfoById(processInstanceId);
                // 转为json对象
                JSONObject object = JSON.parseObject(body);
                log.info("{}",object);
                //todo: 实现审批的业务逻辑，如发消息
                String process_instance = object.getString("process_instance");
                JSONObject object2 = JSON.parseObject(process_instance);
                //发起人id
                String originator_userid = object.getString("originator_userid");
                //获取已审批任务列表
                String tasks = object2.getString("tasks");
                JSONArray array = JSON.parseArray(tasks);
                tasks = array.get(0).toString();
                String tasksLast = array.get(array.size()-1).toString();
                JSONObject objectLast = JSON.parseObject(tasksLast);
                // 获取最早的操作人
                String userIdLast = objectLast.getString("userid");
                JSONObject object3 = JSON.parseObject(tasks);
                //获取操作人的id
                String userid = object3.getString("userid");
                log.info("{}",userid);
                JSONObject obj1 = new JSONObject();
                OapiUserGetResponse userProfile = UserUtil.getUserProfile(AccessTokenUtil.getToken(), userid);
                String mobileNum = userProfile.getMobile();
                obj1.put("name", "您钉钉上有审批任务请及时处理");

//                DySmsHelper.sendSms(mobileNum,obj1, DySmsEnum.DING_TMPLATE_CODE);
            }
            else if (BPMS_INSTANCE_CHANGE.equals(eventType)) {
                // 审批实例状态更新
                bizLogger.info("收到审批实例状态更新: " + plainText);
                log.info("审批实例状态更新~~~~~~~~");
                //todo: 实现审批的业务逻辑，如发消息
                // 调用接口获取审批表单的信息
                String body = callbackService.getInfoById(processInstanceId);
                // 转为json对象
                JSONObject object = JSON.parseObject(body);
                if (obj.containsKey("result") && "agree".equals(result)) {
                    // 管理员同意
                    // 发消息
//                    DingMessageUtil.sendMessageToOriginator(processInstanceId);
                    //String staffId = obj.getString("staffId");
                    //获取发起人id
                    String process_instance = object.getString("process_instance");
                    JSONObject object2 = JSON.parseObject(process_instance);
                    String originator_userid = object2.getString("originator_userid");
                    JSONArray operation_records_array = JSON.parseArray(object2.getString("operation_records"));
                    // 获得数组
                    // 遍历数组

                    if (Constant.PROCESS_CODE.equals(processCode)) {
                        //审批专家模板
                        //保存审批意见
                        for (int i = 0; i < operation_records_array.size(); i++) {
                            // 获取审批意见
                            String remark = operation_records_array.getJSONObject(i).getString("remark");
                            if (remark != null && !"".equals(remark.trim())) {
                                // 把审批意见放入数据库中
                                diyTemporaryApplicantInfoService.update03(remark, originator_userid);
                            }
                        }
                        //更新用户部门
                        UserUtil.updateDingUser(originator_userid);
                        log.info("同意后的用户id："+originator_userid);
                        // 调用保存专家信息的方法  originator_userid 就是钉钉id
                        iDiyProfessorInfoService.saveByJsonObj(object, originator_userid);
                        // 获取专家角色id roleId
                        RoleInfo roleInfo = iSysBaseAPI.getRoleInfoByCode("professor");
                        String roleId = roleInfo.getId();
                        // 根据userid获取id，通过unionid转换
                        String uid = callbackService.getUidByUserId(originator_userid);
                        // 修改临时申请表中的信息为可修改状态
                        diyTemporaryApplicantInfoService.update(new UpdateWrapper<DiyTemporaryApplicantInfo>().set("isdisabled", 2).eq("ding_user_id", uid));
                        // 同意后将status改为专家入库申请通过
                        iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid,"status","专家入库申请通过");
                        Integer integer = iSysBaseAPI.addRole(uid, roleId);
                        log.info("更新专家的角色为正式专家----- {} ", integer == 1 ? "成功" : "失败");
                        String msg = "您的专家入库申请通过啦";
                        OapiUserGetResponse userProfile = UserUtil.getUserProfile(AccessTokenUtil.getToken(), originator_userid);
                        log.info("userProfile=====>"+userProfile.toString());
                        String username = userProfile.getName();
                        String phone = userProfile.getMobile();
                        JSONObject obj1 = new JSONObject();
                        obj1.put("name", username);
                        obj1.put("content", msg);
                        DySmsHelper.sendSms(phone,obj1, DySmsEnum.DING_TMPLATE_CODE);
                    }
                    else if (Constant.MODIFY_PROCESS_CODE.equals(processCode)) {
                        // 修改专家状态审批
                        try {
//                            同意后让isChangeInfo为1,让临时表中的disabled字段为1才能再次提交
                            iDiyProfessorInfoService.updateChangeInfo(originator_userid);
                            iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid, "is_leave", 1);
                            iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid, "status", "申请修改个人信息已通过");
                            diyTemporaryApplicantInfoService.updateIsDisabled(originator_userid);
                            log.info("====修改专家状态为可修改个人信息====");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                    else if (Constant.LEAVE_PROCESS_CODE.equals(processCode)) {
                        //判断是否为请假审批
                        try {
                            iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid, "is_leave", 1);
                            log.info("{}","请假成功");

                        } catch (Exception e) {
                            log.info("{}","请假失败");
                            e.printStackTrace();
                        }

                    }
                    else if(Constant.TERMINATE_LEAVE.equals(processCode)){
                        //判断是否为销假审批
                        try {
                            iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid, "is_leave", 0);
                            log.info("{}","销假成功");
                        } catch (Exception e) {
                            log.info("{}","销假失败");
                            e.printStackTrace();
                        }

                    }
                    else if (Constant.PROFESSOR_CHOOSE_PROCESS_CODE.equals(processCode)) {
                        //判断是否为专家抽取审批
                        //将专家工作状态改为一工作
                        //已审批任务列表
                        String tasks = object2.getString("tasks");
                        JSONArray array = JSON.parseArray(tasks);
                        tasks = array.get(0).toString();
                        JSONObject object3 = JSON.parseObject(tasks);
                        //获取操作人的id
                        String userid = object3.getString("userid");
                        String form_component_values = object2.getString("form_component_values");
                        JSONArray array1 = JSON.parseArray(form_component_values);
                        JSONObject projectObj = (JSONObject) array1.get(0);
                        //该项目对应的项目id
                        String projectId = projectObj.getString("value");
                        QueryWrapper<DiyProjectProfessor> queryWrapper = new QueryWrapper<>();
                        queryWrapper.
                                eq("project_id",projectId).
                                eq("ding_user_id",userid);
                        DiyProjectProfessor one = diyProjectProfessorService.getOne(queryWrapper);
                        if(one.getProfessorInProjectStates()==-3){
                            log.info("该专家已经被管理员在该项目中删除了，专家操作审批后无需操作");
                        }else{
                            //将专家在项目中的状态改为已同意
                            UpdateWrapper<DiyProjectProfessor> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.eq("project_id", projectId).
                                    eq("ding_user_id", userid).
                                    set("professor_in_project_states", 1);
                            diyProjectProfessorService.update(null, updateWrapper);
                            //当前项目的所有信息
                            ProjectProfessorInfo projectProfessorInfo = projectProfessorInfoService.getById(projectId);
                            //变更当前项目的所需专家人数
                            //当前项目的所有专家类型
                            List<DiyProjectOwnProfessorType> projectOwnProfessorTypeList = diyProjectOwnProfessorTypeService.list(new QueryWrapper<DiyProjectOwnProfessorType>()
                                    .lambda().eq(DiyProjectOwnProfessorType::getProjectId, projectId));

                            //根据专家id获取该专家在此项目中的专家类型
                            QueryWrapper<DiyProjectProfessor> wrapper2 = Wrappers.query();
                            wrapper2.eq("project_id", projectId).eq("ding_user_id", userid);
                            List<DiyProjectProfessor> list2 = diyProjectProfessorService.list(wrapper2);
                            //专家在该项目中对应的专家类型
                            String professorInProjectProfessorType = list2.get(0).getProfessorInProjectProfessorType();
                            //记录人数已经满足的专家类型标记数组
                            ArrayList<String> flagFinish = new ArrayList<>();
                            //专家对应的项目类型的先关数据（该类型所需总人数，还需要的人数)
                            DiyProjectOwnProfessorType oneProjectOwnProfessorType = new DiyProjectOwnProfessorType();
                            for (DiyProjectOwnProfessorType projectOwnProfessorType : projectOwnProfessorTypeList) {
                                if (projectOwnProfessorType.getProfessorType().equals(professorInProjectProfessorType)) {
                                    oneProjectOwnProfessorType = projectOwnProfessorType;
                                    //判断该类型专家所需要的人数是否壹，给完成数组添加标记
                                    if (Integer.parseInt(projectOwnProfessorType.getNeedProfessorNumber()) == 1) {
                                        flagFinish.add("");
                                    }
                                }
                                //判断该类型专家所需要的人数是否零，给完成数组添加标记
                                if (Integer.parseInt(projectOwnProfessorType.getNeedProfessorNumber()) == 0) {
                                    flagFinish.add("");
                                }
                            }
                            //修改该类型目前所需的人数和正在考虑中的人数（人数减一）
                            diyProjectOwnProfessorTypeService.update(new UpdateWrapper<DiyProjectOwnProfessorType>().lambda().
                                    eq(DiyProjectOwnProfessorType::getProjectId, projectId).
                                    eq(DiyProjectOwnProfessorType::getProfessorType, professorInProjectProfessorType).
                                    set(DiyProjectOwnProfessorType::getNeedProfessorNumber, Integer.parseInt(oneProjectOwnProfessorType.getNeedProfessorNumber()) - 1).
                                    set(DiyProjectOwnProfessorType::getThinkProfessorNumber, Integer.parseInt(oneProjectOwnProfessorType.getThinkProfessorNumber()) - 1));

                            //判断该项目所有的专家类型所需要的人数是否已经达成完成标准
                            if (flagFinish.size() == projectOwnProfessorTypeList.size()) {
                                //全部同意将项目变为完成状态
                                UpdateWrapper<ProjectProfessorInfo> updateWrapper2 = new UpdateWrapper<>();
                                updateWrapper2.eq("id", projectId).set("project_status", ProjectProfessorInfo.projectStage.FINISH);
                                //给管理员推送消息
                                String message="项目抽取已完成";
                                SimpleDateFormat formatter= new SimpleDateFormat("HH:mm:ss");
                                Date date = new Date(System.currentTimeMillis());
                                DingMessageUtil.sendMessageToOriginator(originator_userid,"通知时间："+formatter.format(date)+"\n"+"通知内容："+message);
                                projectProfessorInfoService.update(null, updateWrapper2);
                            }
                        }
                    }
                    else if(Constant.SUDDEN_LEAVE_PROCESS_CODE.equals(processCode)){
                        //判断是否为专家临时有事（即同意管理员的抽取后突然有事，取不了的请假审批） 紧急请假
                        //判断是否为专家临时有事（即同意管理员的抽取后突然有事，取不了的请假审批）
                        log.info("{}","判断是否为专家临时有事（即同意管理员的抽取后突然有事，去不了的请假审批)");
                        //发起请假的专家Id
                        String leaveProfessorId = originator_userid;
                        log.info("移除专家紧急请假表中的数据");
                        String userid=originator_userid;
                        List<ProjectUrgentStatus> projectUrgentStatuses = diyProjectUrgentStatusService.queryByUserid(userid);
                        String projectid=null;
                        for (int i = 0; i < projectUrgentStatuses.size(); i++) {
                            if(projectUrgentStatuses.get(i).getUrgentLeaveStatus()==1){
                                projectid=projectUrgentStatuses.get(i).getProjectId();
                                diyProjectUrgentStatusService.deleteByuseridAndprojectid(userid,projectid);
                            }
                        }
                        String tasks = object2.getString("tasks");
                        JSONArray array = JSON.parseArray(tasks);
                        tasks = array.get(0).toString();
                        String tasksLast = array.get(array.size()-1).toString();
                        JSONObject object3 = JSON.parseObject(tasks);
                        JSONObject object4 = JSON.parseObject(tasksLast);
                        // 获取最初的操作人id
                        String useridLast = object4.getString("userid");
                        //获取操作人的id(管理员的id)
                        userid = object3.getString("userid");
                        //获取项目id
                        String form_component_values = object2.getString("form_component_values");
                        JSONArray array1 = JSON.parseArray(form_component_values);
                        JSONObject projectObj = (JSONObject) array1.get(0);
                        //该专家请假对应的项目id
                        String projectId = projectObj.getString("value");
                        //查询项目信息
                        ProjectProfessorInfo projectInfo = projectProfessorInfoService.getById(projectId);
                        //如果是完成状态需要在更新专家状态的同时更新项目状态为抽取中
                        if(projectInfo.getProjectStatus()==ProjectProfessorInfo.projectStage.FINISH){
                            //更新项目状态为WAIT
                            projectInfo.setProjectStatus(ProjectProfessorInfo.projectStage.WAIT);
                            projectProfessorInfoService.updateById(projectInfo);
                        }
                        //获取当前的时间
                        Date date = new Date(System.currentTimeMillis());
                       /* //更新专家状态
                        for (int i = 0; i < operation_records_array.size(); i++) {
                            // 获取审批意见
                            String remark = operation_records_array.getJSONObject(i).getString("remark");
                            if (remark != null && !"".equals(remark.trim())) {
                                // 把审批分数放入数据库中
                                diyTemporaryApplicantInfoService.update04(remark, originator_userid);
                            }
                        }*/
                        DiyProjectProfessor professor = diyProjectProfessorService.getOne(new QueryWrapper<DiyProjectProfessor>().lambda().
                                eq(DiyProjectProfessor::getDingUserId, originator_userid).
                                eq(DiyProjectProfessor::getProjectId, projectId));
                        professor.setProfessorInProjectStates(-4);
                        professor.setCreateTime(date);
                        diyProjectProfessorService.updateById(professor);
                        //项目中当前类型的专家所需要的人数加一
                        DiyProjectOwnProfessorType oneProjectProfessorType = diyProjectOwnProfessorTypeService.getOne(new QueryWrapper<DiyProjectOwnProfessorType>().lambda().
                                eq(DiyProjectOwnProfessorType::getProjectId, projectId).
                                eq(DiyProjectOwnProfessorType::getProfessorType, professor.getProfessorInProjectProfessorType()));
                        diyProjectOwnProfessorTypeService.update(new UpdateWrapper<DiyProjectOwnProfessorType>().lambda().
                                eq(DiyProjectOwnProfessorType::getProjectId, projectId).
                                eq(DiyProjectOwnProfessorType::getProfessorType,professor.getProfessorInProjectProfessorType() ).
                                set(DiyProjectOwnProfessorType::getNeedProfessorNumber, Integer.parseInt(oneProjectProfessorType.getNeedProfessorNumber()) + 1));
                        //随机选取以为替补专家
                        log.info("363================================{}",request.getHeader("X-Access-Token"));
                        randmeOneChooseProfessor(projectId,originator_userid,useridLast,request);
                    }
                    else{
                        log.info("其他类型的回调无需处理");
                    }
                }
                else if ("refuse".equals(result)) {
                    // 专家申请表和信息修改的拒绝情况
                    if (Constant.PROCESS_CODE.equals(processCode)) {
                        String process_instance = object.getString("process_instance");
                        JSONObject object2 = JSON.parseObject(process_instance);
                        String originator_userid = object2.getString("originator_userid");
                        JSONArray operation_records_array = JSON.parseArray(object2.getString("operation_records"));
                        // 修改专家表中状态为可修改
                        UpdateWrapper<DiyProfessorInfo> wrapper = new UpdateWrapper<>();
                        wrapper.set("is_change_info",1).eq("ding_user_id",originator_userid);
                        try {
                            iDiyProfessorInfoService.update(wrapper);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        // 获得数组
                        // 遍历数组
                        // 修改专家信息表状态为不可修改
                        for (int i = 0; i < operation_records_array.size(); i++) {
                            // 获取审批意见
                            String remark = operation_records_array.getJSONObject(i).getString("remark");
                            if (remark != null && !"".equals(remark.trim())) {
                                // 把审批意见放入数据库中
                                diyTemporaryApplicantInfoService.update03(remark, originator_userid);
                                log.info("被拒绝了我要把你设置成可以修改信息的人");
                                //修改临时申请人变成能提交的状态
                                diyTemporaryApplicantInfoService.updateIsDisabled02(originator_userid);
                            }
                        }
                        log.info("被拒绝了我要把你设置成可以修改信息的人");
                        DiyProfessorInfo diyProfessorInfo = iDiyProfessorInfoService.queryProfessorInfoByUserId(originator_userid);
                        log.info("先看一看是否是修改信息信息的专家提交来的===>"+diyProfessorInfo);
                        if(diyProfessorInfo!=null){
                            diyTemporaryApplicantInfoService.updateIsDisabled(originator_userid);
                            iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid,"status","专家入库申请未通过");
                        }else {
                            diyTemporaryApplicantInfoService.updateIsDisabled02(originator_userid);
                        }
                        String msg = "您提交的专家入库申请个人信息表审核未通过";
                        OapiUserGetResponse userProfile = UserUtil.getUserProfile(AccessTokenUtil.getToken(), originator_userid);
                        String username = userProfile.getName();
                        String phone = userProfile.getMobile();
                        JSONObject obj1 = new JSONObject();
                        obj1.put("name", username);
                        obj1.put("content", msg);
                        DySmsHelper.sendSms(phone,obj1, DySmsEnum.DING_TMPLATE_CODE);

                    }
                    else if (Constant.PROFESSOR_CHOOSE_PROCESS_CODE.equals(processCode)) {
                        //专家拒绝接受该项目
                        //获取发起人id
                        String process_instance = object.getString("process_instance");
                        JSONObject object2 = JSON.parseObject(process_instance);
                        String originator_userid = object2.getString("originator_userid");
                        //获取操作人的id
                        String tasks = object2.getString("tasks");
                        JSONArray array = JSON.parseArray(tasks);
                        tasks = array.get(0).toString();
                        JSONObject object3 = JSON.parseObject(tasks);
                        String userid = object3.getString("userid");

                        //该项目对应的项目id
                        String form_component_values = object2.getString("form_component_values");
                        JSONArray array1 = JSON.parseArray(form_component_values);
                        JSONObject projectObj = (JSONObject) array1.get(0);
                        String projectId = projectObj.getString("value");

                        QueryWrapper<DiyProjectProfessor> queryWrapper = new QueryWrapper<>();
                        queryWrapper.
                                eq("project_id",projectId).
                                eq("ding_user_id",userid);
                        DiyProjectProfessor one = diyProjectProfessorService.getOne(queryWrapper);
                        //获取当前的时间
                        Date date = new Date(System.currentTimeMillis());
                        if(one.getProfessorInProjectStates()==-3){
                            log.info("该专家已经被管理员在该项目中删除了，专家操作审批后无需操作");
                            one.setCreateTime(date);
                        }else {
                            //将专家工作状态改为拒绝
                            //iDiyProfessorInfoService.updateDiyProfessorOneField(userid, "is_work", 0);
                            //专家拒绝后，需要对项目类型的考虑中人数减一，该操作在randomOneChoose中进行操作
                            //将专家在项目中的状态改为拒接
                            UpdateWrapper<DiyProjectProfessor> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.eq("project_id", projectId).
                                    eq("ding_user_id", userid).
                                    set("professor_in_project_states", 0).
                                    set("create_time",date);
                            diyProjectProfessorService.update(null, updateWrapper);
                            log.info("419================================{}", request.getHeader("X-Access-Token"));
                            randmeOneChooseProfessor(projectId, userid, originator_userid, request);
                        }
                    }
                    else if (Constant.MODIFY_PROCESS_CODE.equals(processCode)){
//                        如果我们提交的修改个人信息审批被拒绝的话isChangInfo设置为66,该专家可以再次提交申请，并不再处于请假状态
                        String process_instance = object.getString("process_instance");
                        JSONObject object2 = JSON.parseObject(process_instance);
                        String originator_userid = object2.getString("originator_userid");
                        JSONArray operation_records_array = JSON.parseArray(object2.getString("operation_records"));

                        // 修改专家表中状态为可修改
                        UpdateWrapper<DiyProfessorInfo> wrapper = new UpdateWrapper<>();
                        diyTemporaryApplicantInfoService.updateIsDisabled02(originator_userid);
                        wrapper.set("status","申请修改个人信息未通过").set("is_leave",0).eq("ding_user_id",originator_userid);
                        try {
                            iDiyProfessorInfoService.update(wrapper);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        // 获得数组
                        // 遍历数组
                        // 修改专家信息表状态为可修改
                        for (int i = 0; i < operation_records_array.size(); i++) {
                            // 获取审批意见
                            String remark = operation_records_array.getJSONObject(i).getString("remark");
                            if (remark != null && !"".equals(remark.trim())) {
                                // 把审批意见放入数据库中
                                iDiyProfessorInfoService.updateDiyProfessorOneField(originator_userid,"professor_approve_msg",remark);
                            }
                        }
                    }
                    else if(Constant.SUDDEN_LEAVE_PROCESS_CODE.equals(processCode)){
                        String process_instance = object.getString("process_instance");
                        JSONObject object2 = JSON.parseObject(process_instance);
                        String userid = object2.getString("originator_userid");
                        log.info("紧急请假专家被拒绝了,直接移除信息");
                        log.info("紧急请假专家被拒绝了用户id"+userid);
                        List<ProjectUrgentStatus> projectUrgentStatuses = diyProjectUrgentStatusService.queryByUserid(userid);
                        String projectid=null;
                        for (int i = 0; i < projectUrgentStatuses.size(); i++) {
                            if(projectUrgentStatuses.get(i).getUrgentLeaveStatus()==1){
                                projectid=projectUrgentStatuses.get(i).getProjectId();
                           diyProjectUrgentStatusService.deleteByuseridAndprojectid(userid,projectid);
                            }
                        }
                    }
                    else{
                        log.info("其他类型的回调无需处理");
                    }
                }
            }
            else if (CallBackEvent.USER_ADD_ORG.equals(eventType)) {
                // 用户进入组织
                bizLogger.info("收到新增用户信息: " + plainText);
                String UserId = obj.getString("UserId");
                JSONArray js = JSONArray.parseArray(UserId);
                log.info("userid"+UserId);
                js.forEach(id->{
                        // 保存存改用户的信息
                        diyDingUserService.toSaveDingUserInfo(id.toString());
                });
            }
            else if (CallBackEvent.USER_LEAVE_ORG.equals(eventType)) {
                // 用户退出组织
                bizLogger.info("收到用户离职信息: " + plainText);
                String UserId = obj.getString("UserId");
                JSONArray js = JSONArray.parseArray(UserId);
                js.forEach(id->{
                    // 获取unionid,因为离职了所以只能去数据库获取
                    String unionId = callbackService.getUnionIdByUserIdFromDB(id.toString());
                    if(unionId !=null &&unionId !=""){
                        // 根据unionId删除相关表中的信息/sendLeaveCause
                        iDiyProfessorInfoService.deleteProfessorByUnionId(unionId);
                        // 删除专家信息表中信息
                        iDiyProfessorInfoService.deleteProfessorByDingId(id.toString());
                        // 如果存在就删除临时专家表中的信息
                        diyTemporaryApplicantInfoService.delete(id.toString());
                        // 删除diy_ding_user表中的数据
                        dingUserService.removeDingUserId(id.toString());
                        diyProfessorScoreService.remove(new QueryWrapper<DiyProfessorScore>().eq("ding_user_id",id.toString()));
                        //删除临时申请人表中的数据
                        diyTemporaryApplicantInfoService.deleByuserid(id.toString());
                    }else{
                        log.info("用户不在专家库内，无需删除");
                    }
                });
                log.info("用户离职成功，数据删除成功");
            }
            else {
                // 其他类型事件处理
                log.info("其他类型的回调不用处理");
            }
            // 返回success的加密信息表示回调处理成功
            return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
        } catch (Exception e) {
            // 失败的情况，应用的开发者应该通过告警感知，并干预修复
            mainLogger.error("失败的情况，应用的开发者应该通过告警感知，并干预修复！" + params, e);
            return null;
        }

    }


    @PostMapping(value = "/sendToDing2")
    public Result<?> sendToCheck2(@RequestBody DiyTemporaryApplicantInfo diyTemporaryApplicantInfo) throws com.baomidou.mybatisplus.extension.exceptions.ApiException {
        log.info("！1111111111111111111！");
        Subject subject = SecurityUtils.getSubject();
        LoginUser user = (LoginUser) subject.getPrincipal();
        log.info(user.toString());
        String username = user.getUsername();
        String jsonStr = callbackService.selUserIdByUnionid(username);
        JSONObject getUserId = JSON.parseObject(jsonStr);
        String userid = getUserId.getString("userid");
        log.info("我要设置用户的钉钉id了"+userid);
        diyTemporaryApplicantInfo.setDingUserId(userid);
        DiyTemporaryApplicantInfo ding_user_id1 = diyTemporaryApplicantInfoService.getOne(new QueryWrapper<DiyTemporaryApplicantInfo>().eq("ding_user_id", userid));
        if (ding_user_id1==null){
            diyTemporaryApplicantInfoService.save(diyTemporaryApplicantInfo);
        }else
        { diyTemporaryApplicantInfoService.update(diyTemporaryApplicantInfo, new UpdateWrapper<DiyTemporaryApplicantInfo>().eq("ding_user_id", userid));}
        try {
            callbackService.sendToDingTalk(diyTemporaryApplicantInfo, userid);
            // 修改专家信息表状态为不可修改
            UpdateWrapper<DiyProfessorInfo> wrapper = new UpdateWrapper<>();
//           修改信息后的专家提交的状态为待审核
            iDiyProfessorInfoService.updateDiyProfessorOneField(userid,"status","专家入库申请待审核");
            wrapper.set("is_change_info",0).eq("ding_user_id",userid);
            iDiyProfessorInfoService.update(wrapper);
            return Result.ok("已发送至审核！");
        } catch (Exception e) {
            return Result.error("出错了！请重新发送");
        }
    }
    @PostMapping(value = "/sendToDing")
    public Result<?> sendToCheck(@RequestBody DiyTemporaryApplicantInfo diyTemporaryApplicantInfo, HttpServletRequest request) throws com.baomidou.mybatisplus.extension.exceptions.ApiException {
        Subject subject = SecurityUtils.getSubject();
        LoginUser user = (LoginUser) subject.getPrincipal();
        //获取token
        String token = request.getHeader("X-Access-Token");
        //获取当前登录用户的unionid username就是unionid
        String username = JwtUtil.getUsername(token);
        // 获取其中的所有数据，放到钉钉表单中
        // 根据unionid获取userid
        String useridStr = callbackService.selUserIdByUnionid(username);
        JSONObject getUserId = JSON.parseObject(useridStr);
        String userid = getUserId.getString("userid");
        diyTemporaryApplicantInfo.setDingUserId(userid);
        int temp = diyTemporaryApplicantInfoService.selectIsDisabled(userid);
        //将表单数据存入数据库中
        //将原有的信息删除
        log.info("我要设置用户的钉钉id了2"+userid);
        DiyTemporaryApplicantInfo ding_user_id1 = diyTemporaryApplicantInfoService.getOne(new QueryWrapper<DiyTemporaryApplicantInfo>().eq("ding_user_id", userid));
        if (ding_user_id1==null){
            diyTemporaryApplicantInfoService.save(diyTemporaryApplicantInfo);
        }else
        {
            diyTemporaryApplicantInfoService.update(diyTemporaryApplicantInfo, new UpdateWrapper<DiyTemporaryApplicantInfo>().eq("ding_user_id", userid));
        }
        try {
            if(temp==1){
                return Result.error("请勿重复提交信息!");
            }
            callbackService.sendToDingTalk(diyTemporaryApplicantInfo,userid);
            return Result.ok("已发送至审核！");
        } catch (Exception e) {
            return Result.error("出错了！请重新发送");
        }
    }

    @GetMapping("/sendAdminErrorList/{errorList}")
    public Result<?> sendAdminErrorList(@PathVariable("errorList") List<String> errorList, HttpServletRequest request) {
        //获取token
        String token = request.getHeader("X-Access-Token");
        log.info("token============================{}",token);
        //获取当前登录用户的unionid username就是unionid
        String username = JwtUtil.getUsername(token);
        log.info("username============================{}",username);

        // 获取当前登录用户的unionid username就是unionid
        String originatorUserId = null;
        if (username != null) {
            originatorUserId = UserUtil.unionIdChageUserId(username);
        }
        if (originatorUserId == null) {
            originatorUserId = (String) redisUtil.get("originator_userid");
        }
        log.info("origin============================{}",originatorUserId);
        //发送项目中哪个类型的专家剩余人数不足
        DingMessageUtil.sendMessageToOriginator(originatorUserId, errorList);
        return Result.ok("人数不够！");
    }

    @RequestMapping("/sendProfessorChooseToDing/{projectId}")
    public Result<?> sendProfessorChooseToDing(@PathVariable("projectId") String projectId, HttpServletRequest request) {
        QueryWrapper<DiyProjectProfessor> wrapper = Wrappers.query();
//        List<String> excludeStates = new ArrayList<>();
//        excludeStates.add("1");//排除已经同意的
//        excludeStates.add("0");//排除已经拒接的
//        excludeStates.add("2");//排除正在考虑的
//        excludeStates.add("-3");//排除被管理员删除的
//        excludeStates.add("-4");//排除临时请假的
        String[] exclude = new String[]{"0", "1", "2", "-4", "-3"};
        wrapper.eq("project_id", projectId).notIn("professor_in_project_states", exclude);
        //查找该项目未被抽取的专家的所有专家
        List<DiyProjectProfessor> list = diyProjectProfessorService.list(wrapper);
        //获取token
        String token = request.getHeader("X-Access-Token");
        //获取当前登录用户的unionid username就是unionid
        String username = JwtUtil.getUsername(token);
        // 获取当前登录用户的unionid username就是unionid
        String originatorUserId = null;
        if (username != null) {
            originatorUserId = UserUtil.unionIdChageUserId(username);
        }
        if (originatorUserId == null) {
            originatorUserId = (String) redisUtil.get("originator_userid");
        }
        if (list.size() > 0) {
            ProjectProfessorInfo projectProfessorInfo = projectProfessorInfoService.getById(projectId);
            ProfessorChoose professorChoose = new ProfessorChoose();
            // 赋值到专门发送到钉钉审批里的vo包下的类
            professorChoose.setProjectId(projectProfessorInfo.getId());
            professorChoose.setProjectName(projectProfessorInfo.getProjectName());
            professorChoose.setProjectType(projectProfessorInfo.getProjectType());
            professorChoose.setProfessorJoinMeetingTime(projectProfessorInfo.getProfessorWorkBeginTime());
            professorChoose.setProfessorJoinMeetingAddress(projectProfessorInfo.getProfessorWorkAddress());
            professorChoose.setProjectFrom(projectProfessorInfo.getProjectFrom());
            professorChoose.setProjectExpectTime(projectProfessorInfo.getProjectExpectTime());
            professorChoose.setProjectAmount(projectProfessorInfo.getProjectAmount());

            for (DiyProjectProfessor professor : list) {
                UpdateWrapper<DiyProjectProfessor> updateWrapper = new UpdateWrapper<>();
                //将专家在项目中的状态改为考虑中
                updateWrapper.eq("project_id", projectId).
                        eq("ding_user_id", professor.getDingUserId()).
                        set("professor_in_project_states", 2);
                diyProjectProfessorService.update(null, updateWrapper);
                // 给专家推送消息
                callbackService.sendProfessorChooseToDingTalk(professorChoose, originatorUserId, professor.getDingUserId());

                //给专家发送短信
                String msg = "你有钉钉审批需要处理";
                OapiUserGetResponse userProfile = UserUtil.getUserProfile(AccessTokenUtil.getToken(), professor.getDingUserId());
                String usernames = userProfile.getName();
                String phone = userProfile.getMobile();
                JSONObject obj1 = new JSONObject();
                obj1.put("name", usernames);
                obj1.put("content", msg);
                try {
                    DySmsHelper.sendSms(phone,obj1, DySmsEnum.DING_TMPLATE_CODE);
                } catch (ClientException e) {
                    e.printStackTrace();
                }
            }
            projectProfessorInfoService.update(new UpdateWrapper<ProjectProfessorInfo>().lambda().
                    eq(ProjectProfessorInfo::getId, projectId).
                    set(ProjectProfessorInfo::getProjectStatus, ProjectProfessorInfo.projectStage.RUNNING));
            return Result.ok("已发送至审核！");
        } else {
            return Result.ok("人数不够！");
        }
    }

    @RequestMapping("/sendLeaveCause")
    public Result<?> sendLeaveCauseToDing(@RequestBody JSONObject jsonObject){
        Result<?> result = new Result();
        //调用业务层，发送到钉钉上
        try {
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            String useridStr = callbackService.selUserIdByUnionid(loginUser.getUsername());
            String userid = JSONObject.parseObject(useridStr).getString("userid");
            jsonObject.put("userId",userid);
            log.info("申请紧急请假的用户id"+userid);
            String projectid = jsonObject.getString("projectId");
            log.info("申请紧急请假的项目id"+projectid);
            ProjectUrgentStatus projectUrgentStatus = new ProjectUrgentStatus();
            projectUrgentStatus.setId(UUID.randomUUID().toString().substring(0,5));
            projectUrgentStatus.setDingUserId(userid);
            projectUrgentStatus.setProjectId(projectid);
//            提交后状态为1，拒绝状态为2，同意状态为3，正常状态为0
            projectUrgentStatus.setUrgentLeaveStatus(1);
            log.info("申请紧急请假的表"+projectUrgentStatus);
            ProjectUrgentStatus status = diyProjectUrgentStatusService.queryByUseridAndProjectId(userid, projectid);
            if(status==null){
                diyProjectUrgentStatusService.addByUseridAndProjectId(projectUrgentStatus);
            }
//            else if (status.getUrgentLeaveStatus()==2){
//                diyProjectUrgentStatusService.updateStatus01(userid,projectid);
//            }
            else {
                result.setSuccess(false);
                result.setMessage("请勿重复提交申请");
                return result;
            }
            callbackService.sendLeaveCauseToDing(jsonObject);
            result.setSuccess(true);
            result.setMessage("发送成功");
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage("发送失败");
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 注册审批，默认执行
     *
     * @throws Exception
     */
    public static String registerCallbackForDD() throws Exception {

//         先删除企业已有的回调
        DingTalkClient client = new DefaultDingTalkClient(URLConstant.DELETE_CALLBACK);
        OapiCallBackDeleteCallBackRequest request = new OapiCallBackDeleteCallBackRequest();
        request.setHttpMethod("GET");
        client.execute(request, AccessTokenUtil.getToken());

        // 重新为企业注册回调
        client = new DefaultDingTalkClient(URLConstant.REGISTER_CALLBACK);
        OapiCallBackRegisterCallBackRequest registerRequest = new OapiCallBackRegisterCallBackRequest();
        registerRequest.setUrl(Constant.CALLBACK_URL_HOST + "/jeecg-boot" + "/callback");
        registerRequest.setAesKey(Constant.ENCODING_AES_KEY);
        registerRequest.setToken(Constant.TOKEN);

        /*
         * ["bpms_instance_change","bpms_task_change","user_add_org","user_leave_org"]
         * 123456
         * xxxxxxxxlvdhntotr3x9qhlbytb18zyz5zxxxxxxxxx
         */
        registerRequest.setCallBackTag(Arrays.asList("bpms_instance_change", "bpms_task_change", CallBackEvent.USER_ADD_ORG, CallBackEvent.USER_LEAVE_ORG));
        OapiCallBackRegisterCallBackResponse registerResponse = client.execute(registerRequest, AccessTokenUtil.getToken());
        if (registerResponse.isSuccess()) {
            log.info("{}","回调注册成功了！！！");
            return "回调注册成功了!!!!";
        }else{
            log.error("{}","回调注册失败了！！！");
            return "注册失败!";
        }
    }

    @AutoLog(value = "项目拥有的专家状态-分页列表查询")
    @ApiOperation(value="项目拥有的专家状态-分页列表查询", notes="项目拥有的专家状态-分页列表查询")
    @GetMapping(value = "/deleteOneProfessor/{projectId}/{dingUserId}/{deleteCause}")
    public Result<?> deleteOneProfessor(@PathVariable("projectId") String projectId,
                                        @PathVariable("dingUserId") String dingUserId,
                                        @PathVariable("deleteCause") String deleteCause,
                                        HttpServletRequest request){

        //项目id
        String id = projectId;
        //该项目的全部信息
        ProjectProfessorInfo projectInfo = projectProfessorInfoService.getById(id);
        ProjectProfessorInfo.projectStage projectStatus = projectInfo.getProjectStatus();

        if(projectStatus==ProjectProfessorInfo.projectStage.RUNNING||projectStatus.equals(ProjectProfessorInfo.projectStage.RUNNING)){
            //给专家推送消息
            String message="由于你长时间未操作专家抽取的审批，您被移除参见此项目的资格";
            SimpleDateFormat formatter= new SimpleDateFormat("HH:mm:ss");
            Date date = new Date(System.currentTimeMillis());
            DingMessageUtil.sendMessageToOriginator(dingUserId,"通知时间："+formatter.format(date)+"\n"+"通知内容："+message);

            //更新项目的状态为：WAIT
            projectInfo.setProjectStatus(ProjectProfessorInfo.projectStage.WAIT);
            projectProfessorInfoService.updateById(projectInfo);
        }else{
            log.info("不需要给专家推送");
        }
            diyProjectProfessorService.update(new UpdateWrapper<DiyProjectProfessor>().lambda().
                    eq(DiyProjectProfessor::getProjectId,projectId).
                    eq(DiyProjectProfessor::getDingUserId,dingUserId).
                    set(DiyProjectProfessor::getProfessorInProjectStates,"-3").
                    set(DiyProjectProfessor::getDeleteCause,deleteCause)
            );
        //更新改专家的状态为已被管理员删除

        Subject subject = SecurityUtils.getSubject();
        LoginUser user = (LoginUser) subject.getPrincipal();

        //项目中考虑的人数减一

        HttpHeaders requestHeaders = new HttpHeaders();
        String token = request.getHeader("X-Access-Token");
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
        requestHeaders.add("X-Access-Token", token);
        String originator_userid="";
        if(user==null){
            originator_userid="admin";
        }else{
            //获取发起人id
            originator_userid = user.getUsername();
            originator_userid=dingApi.getUnionIdByUserId(originator_userid);
        }

        String url = "http://localhost:8009" + request.getContextPath() + "/projectProfessorInfo/randomOneChoose/" + projectId + "/" + dingUserId+"/"+
                originator_userid+"/"+false;
        HttpEntity<MultiValueMap<String, String>> req = new HttpEntity<>(requestHeaders);
        restTemplate.postForEntity(url,req,String.class);
        return Result.ok("删除成功");
    }

    /**
     * 随机抽取一位同类型的专家
     * @param projectId 项目id
     * @param originator_userid  当前审批的发起人
     * @param userid 发起项目的操作者
     * @param request
     */
    public static void randmeOneChooseProfessor(String projectId,String originator_userid,String userid,HttpServletRequest request){
        String url = "http://localhost:8009" + request.getContextPath() + "/projectProfessorInfo/randomOneChoose/" + projectId + "/" + originator_userid + "/" +
                userid + "/" + true;
        log.info("725================================{}",request.getHeader("X-Access-Token"));
        restTemplate.delete(url);
    }
}
